#ifndef __VISION_H__
#define __VISION_H__

#include <iostream>
#include <fstream>
#include <vector>
#include <cv.h>
#include <highgui.h>

#ifdef CUDASURF
#include "../SURFGPU-1.0.1/ipoint.h"
#endif

// Forward declarations
namespace cv 
{
  class Mat;
  class KeyPoint;
  class VideoCapture;
}

struct Pair;
struct SResult;

// Class definition

class CVision 
{
  public:
  enum EStatus
  {
    EStatusOk,
    EStatusErrorFatal,
    EStatusErrorNonFatal,
    EStatusObjectLost,
    EStatusUnknown
  };

  private:
    cv::Mat mMatchFrame;
    cv::Mat mCameraFrame;
    cv::Mat mMask;
    cv::SURF mExtract/*( 500, 4, 2, true )*/;
    std::vector<cv::KeyPoint> mKeypoints;
    std::vector<float>        mDescriptors;
    std::vector<cv::KeyPoint> mMatchedKeypoints;
    float                     mMatchThreshold;
    int                  mFilterBoxSize;
    
    //Vectors used by CUDASURF
#ifdef CUDASURF
  IpVec  ref_ipts;
#endif

    //new for direct access to the cam
    int mCaptureDevice;
    unsigned char* mpImageBuffer;
    int mFrameBpp;
    int mFrameHeight;
    int mFrameWidth;


    // Performance figures in Us
    std::vector<unsigned long> mTHomography;
    std::vector<unsigned long> mTExtract;
    std::vector<unsigned long> mTMatch;
    SResult Capture();
    SResult Capture_old();
    SResult InitCam( const char* Device = "/dev/video0" );

  public:
    enum EKeypoints 
    {
        EKeypointsOriginal,
        EKeypointsMatched
    };

    enum EObstructionStatus
    {
      EObstructionStatusNoObject,
      EObstructionStatusObjectDetected
    };

    CVision( unsigned BytesPerPixel = 24);
    ~CVision();

    SResult Initialize( unsigned Width, unsigned Height, const char* Path);

    SResult Update( EStatus& rStatus, cv::Mat& rHomography, std::ofstream& rFile);

    SResult DetectObstruction( EObstructionStatus& rStatus, double& rDistanceX, double& rDistanceY );

    cv::Mat& GetMatchFrame(void);
    cv::Mat& GetCameraFrame(void);
    cv::VideoCapture& GetCapture(void);

    std::vector<unsigned long>& GetBenchmark(int Id);

    bool FlannFindPairs
    (
      const std::vector<float>& rDescriptors
      , const std::vector<float>& rDescriptorsFrame
      , const int DescriptorSize
      , std::vector<Pair>& rMatchPairs
    );

    void DrawKeyframes
    (
      cv::Mat& Frame
      , EKeypoints
    );
};

// Create SURF object required for feature 
// extraction
// Default values 
// hessianThreshold = 100;
// extended = 1;
// nOctaves = 4;
// nOctaveLayers = 2;

#endif /* __VISION_H__ */
